home *** CD-ROM | disk | FTP | other *** search
- /*======================================================================================================
- Auxiliary Data Structures: task and map
- ======================================================================================================*/
- class task { # task structure
- attribute:
- public int* c1, c2; # all cities
- int* tour; # partial tour
- int sum; # partial sum
- }
-
- class map {
- attribute:
- public int size; # matrix size
- int[_,_] dist; # distance matrix
- private int x = 197; # random number seed
- method:
- public gen (int I; int* ?Cities).
- private loop (int I, J).
- }
-
- map {
- gen(size, []).
- gen(I', [I|Cs]) |- loop(I,I+1); gen(I+1, Cs'). # go thru rows
-
- loop(_, size).
- loop(I', J') |- x' = (4757 * x + 1) % 32768;
- (int) B' = 1 + ((x / 16) % 256); # random number
- dist[I,J]' = B; # initialize (i,j)
- dist[J,I]' = B; # symmetric (j,i)
- loop(I, J+1). # go thru columns
- }
-
- /*======================================================================================================
- Tsp Specifications
- ======================================================================================================*/
- class Tsp { # common Tsp specification
- constant: int bignum = 65535; # greater than all distances
- attribute:
- protected task* queue = []; # task queue
- public int[_,_] dist = nil; # distance matrix
- protected int* best = []; # best tour so far
- int min = bignum; # minimum distance so far
- method:
- protected explore (int* C1, C2, Tour; int Sum, Depth).
- private expand (int* C1, C2, Tour; int Sum, Depth).
- public update (int* Tour; int Sum).
- private append (task* In1, In2, ?Out).
- }
-
- Tsp :: Slave { # Slave specification
- attribute:
- public Master master; # master agent
- method:
- private work0 (). # mutually recursive
- work1 (). # working routines
- }
-
- Tsp :: Master[$done] { # Master specification
- method:
- public run (int[_,_] Dist; int Depth, Count;
- int* ?Best; int ?Min).
- private spawn (int Count).
- public get (task ?Task; int* ?Best; int ?Min).
- }
-
- /*======================================================================================================
- Tsp Implementations
- ======================================================================================================*/
- Tsp { # common Tsp code
- explore(_,_,_,S',_) :- min <= S. # bounded cutoff, pruned
- explore([],[],T':[X'|_],S',_) |- # best tour so far
- update(T,S+dist[X,0]). # wrap around for cycle
- explore(C1',C2',T',S',0) |- # depth = 0
- append(queue,[task{C1,C2,T,S}],queue'). # enqueue new task
- explore(C1',C2',T',S',D') |- # depth > 0
- expand(C1,C2,T,S,D); # expand cities
- expand(C2,C1,T,S,D). # expand cities
-
- expand([],_,_,_,_). # no more cities
- expand([X'|C1'],C2',T':[Y'|Z'],S',D') |- # expand partial tour
- explore(C1,C2,[X,Y|Z],S+dist[X,Y],D-1); # go down 1 level
- expand(C1,[X|C2],T,S,D). # expand current level
-
- update(_,S') :- min <= S. # new result worst than min?
- update(best',min'). # no, update globals
-
- append([],Ys',Ys).
- append([X'|Xs'],Ys',[X|Zs]) |- append(Xs,Ys,Zs'). # append two lists
- }
-
- Slave { # Slave code
- ?- work0(). # starts a working life...
-
- work1() :- master ! update(best, min), work0(). # update master with result
- work0() :- master ! get(Task',B',M'); # get task from master
- (task) task{C1',C2',T',S'} = Task; # extract task attributes
- Tsp::update(B,M); # update best tour locally
- Tsp::explore(C1,C2,T,S,-1); work1(). # explore search space
- work0(). # ...life ends here
- }
-
- Master { # Master code
- run(dist':$[N',N],Depth',Count',best,min) :- # user invocation
- best' = []; # no best tour yet
- min' = bignum; # a big number
- (map) Map' = map{N,dist}; # create map object
- Map ! gen(0,[C'|Cs']); # generate random weights
- Tsp::explore(Cs,[],[C],0,Depth); # generate tasks
- spawn(Count); # spawn slave agents
- $done ! wait(Count). # wait till all finished
-
- spawn(0). # end of procreation
- spawn(I') |- (Slave) _ = Slave{dist,self}; # spawn a new slave
- spawn(I-1). # spawning more slaves
-
- get(_,best,min) :- queue == []; $done ! post(1). # queue empty? wakeup!
- get(X,best,min) :- (task*) [X'|queue'] = queue; # dequeue task
- X.sum < min. # task looks ok?
- get(X,best,min) |- get(X',_,_). # no, skip to next task
- }
-
- /*======================================================================================================
- The End
- ======================================================================================================*/
-